// ============================================
// 01 - 变量与可变性 (Variables and Mutability)
// ============================================

/// Rust 中的变量默认是不可变的(immutable)
/// 这是 Rust 提供的众多安全特性之一
pub fn variable_basics() {
    println!("\n=== 变量基础 ===");
    
    // 不可变变量 - 使用 let 关键字
    let x = 5;
    println!("不可变变量 x 的值是: {}", x);
    
    // 下面这行代码会导致编译错误，因为 x 是不可变的
    // x = 6; // ❌ 错误: cannot assign twice to immutable variable
    
    // 可变变量 - 使用 let mut 关键字
    let mut y = 5;
    println!("可变变量 y 的初始值是: {}", y);
    y = 6;
    println!("可变变量 y 的新值是: {}", y);
}

/// 变量遮蔽 (Shadowing)
/// 可以使用 let 关键字重新声明同名变量
pub fn shadowing() {
    println!("\n=== 变量遮蔽 ===");
    
    let x = 5;
    println!("x 的初始值: {}", x);
    
    // 遮蔽之前的 x
    let x = x + 1;
    println!("第一次遮蔽后 x 的值: {}", x);
    
    {
        // 在内部作用域中遮蔽
        let x = x * 2;
        println!("内部作用域中 x 的值: {}", x);
    }
    
    // 离开内部作用域后，x 恢复为外部作用域的值
    println!("外部作用域中 x 的值: {}", x);
    
    // 遮蔽允许改变值的类型
    let spaces = "   ";
    println!("spaces 是字符串: '{}'", spaces);
    
    let spaces = spaces.len();
    println!("spaces 现在是数字: {}", spaces);
}

/// 常量 (Constants)
/// 常量使用 const 关键字声明，必须标注类型，且值必须在编译时确定
const MAX_POINTS: u32 = 100_000;
const PI: f64 = 3.14159;

pub fn constants() {
    println!("\n=== 常量 ===");
    println!("最大点数: {}", MAX_POINTS);
    println!("圆周率: {}", PI);

    const AABB: i32 = 3;
    
    // 常量与不可变变量的区别:
    // 1. 常量不能使用 mut
    // 2. 常量必须标注类型
    // 3. 常量可以在任何作用域中声明，包括全局作用域
    // 4. 常量只能被设置为常量表达式，不能是运行时计算的值
}

/// 变量类型推断
pub fn type_inference() {
    println!("\n=== 类型推断 ===");
    
    // Rust 可以根据值推断类型
    let x = 42; // 推断为 i32
    println!("推断的整数: {}", x);
    
    let y = 3.14; // 推断为 f64
    println!("推断的浮点数: {}", y);
    
    let z = true; // 推断为 bool
    println!("推断的布尔值: {}", z);
    
    // 也可以显式标注类型
    let a: i64 = 100;
    println!("显式声明的 i64: {}", a);
}

/// 未使用的变量
pub fn unused_variables() {
    println!("\n=== 未使用的变量 ===");
    
    // 如果声明了变量但没有使用，编译器会发出警告
    // let unused = 42; // ⚠️ 警告: unused variable
    
    // 可以使用下划线前缀来告诉编译器这是故意的
    let _unused = 42; // ✅ 不会警告
    println!("可以使用下划线前缀来避免未使用变量警告");
}

/// 变量绑定的析构
pub fn destructuring() {
    println!("\n=== 变量绑定的析构 ===");
    
    // 元组析构
    let (x, y, z) = (1, 2, 3);
    println!("元组析构: x={}, y={}, z={}", x, y, z);
    
    // 数组析构
    let [a, b, c] = [10, 20, 30];
    println!("数组析构: a={}, b={}, c={}", a, b, c);
    
    // 部分析构 - 使用 .. 忽略其余部分
    let (first, .., last) = (1, 2, 3, 4, 5);
    println!("部分析构: first={}, last={}", first, last);
}


/// 主函数 - 演示所有功能
#[allow(dead_code)]
pub fn main() {
    println!("╔════════════════════════════════════════╗");
    println!("║   Rust 变量与可变性教程                ║");
    println!("╚════════════════════════════════════════╝");
    
    variable_basics();
    shadowing();
    constants();
    type_inference();
    unused_variables();
    destructuring();
    
    println!("\n✅ 变量教程完成！");
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_variable_basics() {
        let x = 5;
        assert_eq!(x, 5);
        
        let mut y = 5;
        y = 6;
        assert_eq!(y, 6);
    }
    
    #[test]
    fn test_shadowing() {
        let x = 5;
        let x = x + 1;
        assert_eq!(x, 6);
    }
    
    #[test]
    fn test_constants() {
        assert_eq!(MAX_POINTS, 100_000);
        assert_eq!(PI, 3.14159);
    }
}

